package controller;

import java.awt.Color;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;

import javax.swing.JOptionPane;

import common.Change;

import main.GUIManager;
import model.DrawLine;
import model.DrawObject;
import model.DrawingModel;
import view.DrawingView;
import view.GeometryDescriptor;
import view.ViewObject;

public class DrawingController
{
	
	private DrawingModel model;
	private DrawingView view;
	
	private State state;
	public Pallette menuState;
	
	private Point lastMove;
	
	public DrawingController(DrawingModel model, DrawingView view) 
	{
		menuState = Pallette.SELECT;
		this.model = model;
		this.view = view;
		state = new IdleSt(this);
	}
	
	public void testMove()
	{
		DrawObject temp = model.getDrawObject(0);
		
		temp.setX1(temp.getX1() + 5);
		temp.setY1(temp.getY1() + 5);
	}

	public DrawingView getView()
	{
		return view;
	}
	
	public void setState(State state)
	{
		this.state = state;
	}
	
	/*
	 * ****************************************************
	 * 				Methods for input events
	 * ****************************************************
	 * 
	 */
	
	public void mouseMove(MouseEvent e) 
	{
		if ( (e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) != MouseEvent.BUTTON1_DOWN_MASK )
			return;

		state.update(Input.MM, InputMod.LD, e.getPoint());
	}

	public void mouseDown(MouseEvent e) 
	{
		if (e.getButton() != MouseEvent.BUTTON1)
			return;
		
		lastMove = e.getPoint();
		state.update(Input.MD, InputMod.LD, e.getPoint());
	}

	public void mouseUp(MouseEvent e) 
	{
		if (e.getButton() != MouseEvent.BUTTON1)
			return;
		
		state.update(Input.MU, InputMod.LU, e.getPoint());
		
	}

	public void keyPressed(KeyEvent e) 
	{
		if ( e.getKeyCode() == KeyEvent.VK_BACK_SPACE )
			this.state.update(Input.KD, InputMod.BACKSP, '0');
		else
			this.state.update(Input.KD, InputMod.SYMBOL, e.getKeyChar());
	}
	
//	public void keyTyped(KeyEvent e)
//	{
//		System.out.println("Typed");
//		this.state.update(Input.KD, InputMod.SYMBOL, e.getKeyChar());
//	}
	
	/*
	 * ****************************************************
	 * 						Other
	 * ****************************************************
	 * 
	 */	
	
	public void selectObject(GeometryDescriptor eg)
	{
		view.setSelectedObjDesc(eg);
		view.repaint();
	}
	
	public void dragSelectedObject(Point p) 
	{
		int dx = p.x - lastMove.x;
		int dy = p.y - lastMove.y;
		
		ViewObject selection = view.getSelectedObject();
		
		selection.deltaTranslateObject(dx, dy);
		lastMove = p;
	}

	public void dragSelectedPoint(Point p) 
	{
		int dx = p.x - lastMove.x;
		int dy = p.y - lastMove.y;
		
		int pointNo = view.getSelectedObjDesc().getControlPoint();
		ViewObject selection = view.getSelectedObject();
		
		selection.deltaTranslatePoint(pointNo, dx, dy);
		lastMove = p;
	}

	public void deleteLetter() 
	{		
		int i_char = view.getSelectedObjDesc().getCharIndex();
		int i_obj = view.getSelectedObjDesc().getIndex();
		DrawObject obj = model.getDrawObject(i_obj);
		
		if (obj.getText().equals(""))
			return;
		
		if (obj.getText().length() == 1)
		{
			view.getSelectedObjDesc().setCharIndex(0);
			obj.setText("");
			return;
		}
		
		String text_old = obj.getText();
		String text_new = "";
		
		text_new = text_old.substring(0, i_char);
		text_new = text_new + text_old.substring(i_char + 1);
		
		int new_i_char = (i_char == 0)? 0 : i_char - 1;
		view.getSelectedObjDesc().setCharIndex(new_i_char);
		
		obj.setText(text_new);
	}

	public void insertLetter(char letter)
	{
		int i_char = view.getSelectedObjDesc().getCharIndex();
		int i_obj = view.getSelectedObjDesc().getIndex();
		DrawObject obj = model.getDrawObject(i_obj);
		
		if (obj.getText().equals(""))
		{
			obj.setText("" + letter);
			return;
		}
		
		String text_old = obj.getText();
		String text_new = "";
		
		text_new = text_old.substring(0, i_char+1);
		text_new = text_new + letter + text_old.substring(i_char + 1);
		
		view.getSelectedObjDesc().setCharIndex(i_char + 1);
		
		obj.setText(text_new);
	}

	public void openFile(String f)
	{
		
		GUIManager.getInstance().addGUI(f);
		
	}

	public void closeView()
	{
		if (model.countObservers() > 1 || !model.unsavedChanges())
		{
			model.deleteObserver(view);
			view.getJFrame().dispose();
			return;
		}
				
		int response = JOptionPane.showConfirmDialog(view, "Do you want to save your changes?");
		
		if (response == JOptionPane.YES_OPTION)
		{
			view.saveFile();
			model.deleteObserver(view);
			view.getJFrame().dispose();
		}
		else if (response == JOptionPane.NO_OPTION)
		{
			model.deleteObserver(view);
			view.getJFrame().dispose();
		}
		else if (response == JOptionPane.CANCEL_OPTION)
		{
			// do nothing
		}
	}

	public void saveAs(String path) 
	{
		model.deleteObserver(view);
		
		// you might need to remove the unreferenced model from the GUIManager
		
		model = new DrawingModel(model);
		model.deleteObservers();
		model.setFileName(path);
		model.addObserver(view);
		
		view.setModel(model);
		
		GUIManager.getInstance().addModel(model);
		
		model.save();
	}

	public void save()
	{
		model.save();
	}

	public void setSelectionColor(Color col) 
	{
		int index = view.getSelectedObjDesc().getIndex();
		if ( index == -1)
			return;
		
		DrawObject obj = model.getDrawObject( index );
		
		obj.setRed( col.getRed() );
		obj.setGreen( col.getGreen() );
		obj.setBlue( col.getBlue() );
		
	}

	public void setSelectionThickness(int thickness)
	{
		int index = view.getSelectedObjDesc().getIndex();
		if ( index == -1)
			return;
		
		DrawObject obj = model.getDrawObject( index );
		
		obj.setThickness(thickness);
		
	}

	public void changeState(Pallette menu) 
	{
		menuState = menu;
		
		

		
	}

//	public DrawObject createNewObject(Point p) 
//	{
//		switch (menuState)
//		{
//		case SELECT:
//			break;
//		case TEXT:
//			break;
//		case LINE:
//			return new DrawLine();
//			break;
//		case CURVE:
//			break;
//		case E_RECT:
//			break;
//		case F_RECT:
//			break;
//		case E_ELLIP:
//			break;
//		case F_ELLIP:
//			break;
//		}
//		
//	}

}
